using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using MultiTCPProxy.Models;

namespace MultiTCPProxy.Services
{
    /// <summary>
    /// 代理服务管理类，负责管理多个TCP代理实例
    /// </summary>
    public class ProxyManager
    {
        private readonly string _configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "proxyconfig.xml");
        private readonly Dictionary<string, TCPProxyService> _proxyServices = new Dictionary<string, TCPProxyService>();
        
        public ObservableCollection<ProxyConfig> ProxyConfigs { get; private set; } = new ObservableCollection<ProxyConfig>();
        
        public event EventHandler<ProxyEventArgs> ConnectionEstablished;
        public event EventHandler<ProxyEventArgs> ConnectionClosed;
        public event EventHandler<ProxyDataEventArgs> DataTransferred;
        
        private static ProxyManager _instance;
        public static ProxyManager Instance => _instance ?? (_instance = new ProxyManager());
        
        private ProxyManager()
        {
            LoadConfig();
        }
        
        /// <summary>
        /// 加载代理配置
        /// </summary>
        public void LoadConfig()
        {
            if (File.Exists(_configPath))
            {
                try
                {
                    var serializer = new XmlSerializer(typeof(List<ProxyConfig>));
                    using (var reader = new StreamReader(_configPath))
                    {
                        var configs = (List<ProxyConfig>)serializer.Deserialize(reader);
                        ProxyConfigs = new ObservableCollection<ProxyConfig>(configs);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"加载配置失败: {ex.Message}");
                    ProxyConfigs = new ObservableCollection<ProxyConfig>();
                }
            }
        }
        
        /// <summary>
        /// 保存代理配置
        /// </summary>
        public void SaveConfig()
        {
            try
            {
                var serializer = new XmlSerializer(typeof(List<ProxyConfig>));
                using (var writer = new StreamWriter(_configPath))
                {
                    serializer.Serialize(writer, ProxyConfigs.ToList());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"保存配置失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 添加代理配置
        /// </summary>
        public void AddProxy(ProxyConfig config)
        {
            if (ProxyConfigs.Any(p => p.Name == config.Name))
            {
                throw new InvalidOperationException($"已存在名称为 '{config.Name}' 的代理配置");
            }
            
            ProxyConfigs.Add(config);
            SaveConfig();
        }
        
        /// <summary>
        /// 更新代理配置
        /// </summary>
        public void UpdateProxy(ProxyConfig config)
        {
            var existingConfig = ProxyConfigs.FirstOrDefault(p => p.Name == config.Name);
            if (existingConfig == null)
            {
                throw new InvalidOperationException($"未找到名称为 '{config.Name}' 的代理配置");
            }
            
            // 如果代理正在运行，先停止
            if (existingConfig.IsEnabled)
            {
                StopProxy(existingConfig.Name);
            }
            
            // 更新配置
            existingConfig.ListenPort = config.ListenPort;
            existingConfig.TargetIP = config.TargetIP;
            existingConfig.TargetPort = config.TargetPort;
            
            SaveConfig();
        }
        
        /// <summary>
        /// 删除代理配置
        /// </summary>
        public void RemoveProxy(string name)
        {
            var config = ProxyConfigs.FirstOrDefault(p => p.Name == name);
            if (config == null) return;
            
            // 如果代理正在运行，先停止
            if (config.IsEnabled)
            {
                StopProxy(name);
            }
            
            ProxyConfigs.Remove(config);
            SaveConfig();
        }
        
        /// <summary>
        /// 启动指定代理服务
        /// </summary>
        public void StartProxy(string name)
        {
            var config = ProxyConfigs.FirstOrDefault(p => p.Name == name);
            if (config == null) return;
            
            if (_proxyServices.ContainsKey(name))
            {
                // 代理服务已存在，可能已经启动
                return;
            }
            
            try
            {
                var proxyService = new TCPProxyService(config);
                
                proxyService.ConnectionEstablished += (s, e) => ConnectionEstablished?.Invoke(s, e);
                proxyService.ConnectionClosed += (s, e) => ConnectionClosed?.Invoke(s, e);
                proxyService.DataTransferred += (s, e) => DataTransferred?.Invoke(s, e);
                
                proxyService.Start();
                _proxyServices[name] = proxyService;
            }
            catch (Exception ex)
            {
                config.Status = $"启动失败: {ex.Message}";
                throw;
            }
        }
        
        /// <summary>
        /// 停止指定代理服务
        /// </summary>
        public void StopProxy(string name)
        {
            if (_proxyServices.TryGetValue(name, out var proxyService))
            {
                proxyService.Stop();
                _proxyServices.Remove(name);
            }
        }
        
        /// <summary>
        /// 启动所有代理服务
        /// </summary>
        public void StartAllProxies()
        {
            foreach (var config in ProxyConfigs)
            {
                try
                {
                    StartProxy(config.Name);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"启动代理 '{config.Name}' 失败: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// 停止所有代理服务
        /// </summary>
        public void StopAllProxies()
        {
            foreach (var name in _proxyServices.Keys.ToList())
            {
                StopProxy(name);
            }
        }
    }
}